package com.gitee.wsl.net.server.role.admin

import com.gitee.wsl.net.exceptions.Exceptions
import io.ktor.server.application.ApplicationCall
import io.ktor.server.auth.Principal
import io.ktor.server.sessions.get
import io.ktor.server.sessions.sessions
import kotlinx.serialization.Serializable
import kotlin.js.ExperimentalJsExport
import kotlin.js.JsExport

/**
 * Role uer in app
 */
@OptIn(ExperimentalJsExport::class)
@JsExport
enum class AdminRole {
    GUEST, MANAGER, ADMIN
}

/**
 * Admin response
 */
@OptIn(ExperimentalJsExport::class)
@JsExport
@Serializable
data class AdminResponse(
    val id: Int,
    val email: String,
    val role: AdminRole,
)

/**
 * Session cookie
 */
data class SessionUser(
    val userId: Int,
    val role: String,
    val token: String
) : Principal

/**
 * Check role
 */
fun ApplicationCall.checkRole(vararg roles: AdminRole): AdminRole {
    val session = sessions.get<SessionUser>()
    val role = if (session == null) AdminRole.GUEST else AdminRole.valueOf(session.role)
    if (!roles.contains(role)) throw Exceptions.Forbidden()
    return role
}

/**
 * All roles allowed
 */
fun ApplicationCall.checkRoleFull(): AdminRole {
    return checkRole(AdminRole.MANAGER, AdminRole.ADMIN, AdminRole.GUEST)
}

/**
 * Auth roles allowed
 */
fun ApplicationCall.checkRoleAuth(): AdminRole {
    return checkRole(AdminRole.MANAGER, AdminRole.ADMIN)
}

/**
 * Admin role allowed
 */
fun ApplicationCall.checkRoleAdmin(): AdminRole {
    return checkRole(AdminRole.ADMIN)
}

/**
 * Manager role allowed
 */
fun ApplicationCall.checkRoleManager(): AdminRole {
    return checkRole(AdminRole.MANAGER)
}

/**
 * Guest role allowed
 */
fun ApplicationCall.checkRoleGuest(): AdminRole {
    return checkRole(AdminRole.GUEST)
}